﻿using NHibernate;
using NHibernate.Cfg;
using NHibernate.Tool.hbm2ddl;
using NUnit.Framework;
using TestBat.Models.Tests.Mocks.Models.Domain;

namespace TestBat.Models.Tests.NHBugs
{
    public class RefreshDirtySessionBug
    {
        [SetUp]
        public virtual void SetUp()
        {
            var cfg = new Configuration();
            cfg.Configure();
            cfg.AddAssembly("TestBat.Models.Tests");
            sessionFactory = cfg.BuildSessionFactory();

            // export schema
            new SchemaExport(cfg).Execute(false, true, false);
        }

        [Test]
        public void Test()
        {
            // save test-object graph
            TestObject o = new TestObject();
            o.TestValue = "TestValue";
            AssociatedTestObject ao1 = new AssociatedTestObject();
            ao1.AssociatedTestValue = "AssociatedTestValue1";
            ao1.TestObject = o;
            AssociatedTestObject ao2 = new AssociatedTestObject();
            ao2.AssociatedTestValue = "AssociatedTestValue2";
            ao2.TestObject = o;
            using (ISession s = sessionFactory.OpenSession())
            using (ITransaction t = s.BeginTransaction())
            {
                s.Save(o);

                t.Commit();
                s.Flush();

                Assert.IsFalse(s.IsDirty());
            }

            // get object from DB again, change values (and associations), refresh it and check dirtiness
            using (ISession s = sessionFactory.OpenSession())
            using (ITransaction t = s.BeginTransaction())
            {
                o = s.Get<TestObject>(o.ID);
                Assert.AreEqual("TestValue", o.TestValue);

                o.TestValue = "ChangedTestValue";
                Assert.IsTrue(s.IsDirty());
                Assert.AreEqual("ChangedTestValue", o.TestValue);

                ao1 = s.Get<AssociatedTestObject>(ao1.ID);
                ao1.AssociatedTestValue = "ChangedAssociatedTestValue1";
                Assert.IsTrue(s.IsDirty());
                Assert.AreEqual("ChangedAssociatedTestValue1", ao1.AssociatedTestValue);

                ao2 = s.Get<AssociatedTestObject>(ao2.ID);
                ao2.TestObject = null;
                s.Delete(ao2);
                Assert.IsTrue(s.IsDirty());
                Assert.AreEqual(1, o.AssociatedTestObjects.Count);

                s.Refresh(o);

                // asserts which still work
                Assert.AreEqual("TestValue", o.TestValue);
                Assert.AreEqual(2, o.AssociatedTestObjects.Count);
                Assert.AreEqual("AssociatedTestValue1", ao1.AssociatedTestValue);

                // assert which doesn't work
                //Assert.IsFalse(s.IsDirty());

                s.Flush();
            }
        }

        protected ISessionFactory sessionFactory;
    }
}
